package city.spring.modules.material.service.impl;

import city.spring.modules.material.entity.*;
import city.spring.modules.material.repository.MaterialdeliveryMaterialExtRepository;
import city.spring.modules.material.repository.MaterialdeliveryRepository;
import city.spring.modules.material.service.*;
import city.spring.modules.material.vo.MaterialdeliveryMaterialVO;
import city.spring.modules.material.vo.MaterialdeliveryVO;
import city.spring.modules.material.vo.MaterialwarehousingMaterialVO;
import city.spring.modules.material.vo.PrintDeliveryVO;
import city.spring.modules.personnel.entity.EmployeeEntity;
import city.spring.modules.personnel.service.EmployeeService;
import city.spring.modules.system.entity.OrganizationEntity;
import city.spring.modules.system.entity.UserEntity;
import city.spring.modules.system.service.OrganizationService;
import city.spring.modules.system.service.UserService;
import city.spring.utils.UserUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.NonNull;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Service：物资出库
 *
 * @author 谢金婷
 * @date 2020-07-02 13:41:43
 */
@CacheConfig(cacheNames = {MaterialdeliveryServiceImpl.CACHE_NAME})
@Transactional(rollbackFor = Throwable.class)
@Service
public class MaterialdeliveryServiceImpl extends ServiceImpl<MaterialdeliveryRepository, MaterialdeliveryEntity> implements MaterialdeliveryService {

    private final MaterialdeliveryMaterialExtRepository deliveryMaterialExtRepository;
    private final MaterialreceiptService materialreceiptService;
    private final UserService userService;
    private final MaterialdeliveryRepository materialdeliveryRepository;
    private final EmployeeService employeeService;
    private final MaterialwarehousingMaterialExtService materialwarehousingMaterialExtService;
    private final MaterialwarehousingService materialwarehousingService;
    private final MaterialQuantityService materialQuantityService;
    private final OrganizationService organizationService;

    public MaterialdeliveryServiceImpl(MaterialdeliveryMaterialExtRepository deliveryMaterialExtRepository, MaterialreceiptService materialreceiptService, UserService userService, MaterialdeliveryRepository materialdeliveryRepository, EmployeeService employeeService, MaterialwarehousingMaterialExtService materialwarehousingMaterialExtService, MaterialwarehousingService materialwarehousingService, MaterialQuantityService materialQuantityService, OrganizationService organizationService) {
        this.deliveryMaterialExtRepository = deliveryMaterialExtRepository;
        this.materialreceiptService = materialreceiptService;
        this.userService = userService;
        this.materialdeliveryRepository = materialdeliveryRepository;
        this.employeeService = employeeService;
        this.materialwarehousingMaterialExtService = materialwarehousingMaterialExtService;
        this.materialwarehousingService = materialwarehousingService;
        this.materialQuantityService = materialQuantityService;
        this.organizationService = organizationService;
    }

    @Override
    public void saveMaterialdelivery(MaterialdeliveryEntity entity, @NonNull Principal user) {

        /**
         * 出库信息
         */
        // 出库时间=当前系统时间
        entity.setDeliverydate(new Date());
        entity.setCancellation("已出库");
        //登记人
        //当前用户
        UserEntity userEntity = userService.getUserByIdOrAccount(user.getName());
        entity.setUsersId(userEntity.getId());

        /**
         * 领用单信息
         */
        // 获取领用单信息
        MaterialreceiptEntity materialreceiptEntity = materialreceiptService.getById(entity.getMaterialreceiptId());
        materialreceiptEntity.setDeliveryStatus("已出库");
        // 更新领用单信息
        materialreceiptService.lambdaUpdate()
                .set(MaterialreceiptEntity::getDeliveryStatus, materialreceiptEntity.getDeliveryStatus())
                .eq(MaterialreceiptEntity::getId, materialreceiptEntity.getId())
                .update();

        if (!save(entity)) {
            throw new RuntimeException("保存信息失败");
        }
    }

    @Override
    public void updateMaterialdelivery(MaterialdeliveryEntity entity) {
        // 使用 updateById(entity); 修改数据时，将会修改 entity 对象中所有非null数据，如果某个字段为null，将会忽略该字段的修改
        boolean update = updateById(entity);
        if (!update) {
            throw new RuntimeException("修改信息失败");
        }
    }

    @Override
    public void deleteMaterialdelivery(String primaryKey) {
        removeById(primaryKey);
        // 删除包括的出库物资表的信息
        List<MaterialdeliveryMaterialExtEntity> materialdeliveryMaterials = deliveryMaterialExtRepository.getByDeliveryId(primaryKey);
        System.out.println("MaterialdeliveryMaterials" + materialdeliveryMaterials);
        if (!materialdeliveryMaterials.isEmpty()) {
            List<String> materialdeliveryMaterialId = materialdeliveryMaterials.stream().map(MaterialdeliveryMaterialExtEntity::getId).collect(Collectors.toList());
            deliveryMaterialExtRepository.deleteBatchIds(materialdeliveryMaterialId);
        }
    }

    @Override
    public void deleteMaterialdelivery(List<String> primaryKeys) {
        removeByIds(primaryKeys);
    }

    @Override
    public MaterialdeliveryVO getMaterialdeliveryById(String id) {
        MaterialdeliveryEntity deliveryEntity = materialdeliveryRepository.getById(id);
        System.out.println("deliveryEntity" + deliveryEntity);
        MaterialdeliveryVO deliveryVO = new MaterialdeliveryVO(deliveryEntity);

        // 加载物资列表
        deliveryVO.setMaterials(deliveryMaterialExtRepository.getDeliveryMaterials(id));

        return deliveryVO;
    }

    @Override
    public IPage<MaterialdeliveryVO> listPage(Page<? extends MaterialdeliveryEntity> page, Wrapper<? extends MaterialdeliveryEntity> wrapper) {
        return baseMapper.listPage(page, wrapper);
    }

    @Override
    public PrintDeliveryVO getPrintDelivery(List<String> ids) {

        List<MaterialdeliveryEntity> list;
        if (ids.isEmpty()) {
            list = new ArrayList<>();
        } else {
            list = lambdaQuery().in(MaterialdeliveryEntity::getId, ids).list();
        }
        Set<String> collect = list.stream().map(MaterialdeliveryEntity::getId).collect(Collectors.toSet());
        if (collect.size() != 1) {
            throw new RuntimeException("请只选择一个出库单");
        }
        PrintDeliveryVO vo = new PrintDeliveryVO();
        vo.setPreparer(UserUtils.getUser().getNickname());
        // 生成打印时所需要的打印明细
        List<PrintDeliveryVO.PrintDeliveryRecordVO> recordVOList = list.stream().map(item -> {
            EmployeeEntity employeeEntity = employeeService.getById(item.getUserId());
            EmployeeEntity employeeEntity1 = employeeService.getById(item.getUsersId());
            MaterialreceiptEntity materialreceiptEntity = materialreceiptService.getById(item.getMaterialreceiptId());
            EmployeeEntity employeeEntity2 = employeeService.getById(materialreceiptEntity.getReceipter());
            OrganizationEntity organizationEntity = organizationService.getById(item.getDeliverydepartmentId());
            PrintDeliveryVO.PrintDeliveryRecordVO recordVO = new PrintDeliveryVO.PrintDeliveryRecordVO();
            recordVO.setId(item.getId());
            recordVO.setMaterialreceiptId(item.getMaterialreceiptId());
            recordVO.setDestination(item.getDestination());
            recordVO.setApplication(item.getApplication());
            recordVO.setDeliverydate(item.getDeliverydate());
            recordVO.setReceipterName(employeeEntity2.getName());
            recordVO.setUserId(item.getUserId());
            recordVO.setName(employeeEntity.getName());
            recordVO.setDepartmentName(organizationEntity.getTitle());
            recordVO.setUsersId(item.getUsersId());
            recordVO.setUsername(employeeEntity1.getName());
            recordVO.setCancellation(item.getCancellation());
            return recordVO;
        }).collect(Collectors.toList());
        vo.setList(recordVOList);
        return vo;
    }

    @Override
    public void checkCancellation(String id, MaterialdeliveryEntity entity) {
        if (entity.getCancellation().equals("已作废")) {
            throw new RuntimeException("该出库单已作废，无需操作");
        } else {
            entity.setCancellation("已作废");
            // 出库单下的物资信息
            List<MaterialdeliveryMaterialVO> deliveryMaterials = deliveryMaterialExtRepository.getDeliveryMaterials(id);
            // 作废后更新入库物资剩余库存数量和库存表 领用单修改为未出库
            for (MaterialdeliveryMaterialVO deliveryMaterial : deliveryMaterials) {
                // 1.更新入库物资剩余数量 若剩余数量=入库数量，isCan更新为可以
                // 入库物资信息
                MaterialwarehousingMaterialExtEntity materialwarehousingMaterialExtEntity = materialwarehousingMaterialExtService.getById(deliveryMaterial.getMaterialwarehousingMaterialId());
                BigDecimal remainingQuantity = materialwarehousingMaterialExtEntity.getRemainingQuantity() == null ? BigDecimal.ZERO : materialwarehousingMaterialExtEntity.getRemainingQuantity();
                // 剩余数量
                materialwarehousingMaterialExtEntity.setRemainingQuantity(remainingQuantity.add(deliveryMaterial.getDeliveryquantity()));
                materialwarehousingMaterialExtService.lambdaUpdate()
                        .set(MaterialwarehousingMaterialExtEntity::getRemainingQuantity, materialwarehousingMaterialExtEntity.getRemainingQuantity())
                        .eq(MaterialwarehousingMaterialExtEntity::getId, materialwarehousingMaterialExtEntity.getId())
                        .update();

                List<MaterialwarehousingMaterialVO> warehousingMaterials = materialwarehousingMaterialExtService.getWarehousingMaterials(materialwarehousingMaterialExtEntity.getMaterialwarehousingId());
                int mm = 0;
                for (MaterialwarehousingMaterialVO materialwarehousingMaterial : warehousingMaterials) {
                    if (materialwarehousingMaterial.getWarehousingquantity().compareTo(materialwarehousingMaterial.getRemainingQuantity()) == 0) {
                        mm = mm + 1;
                    }
                    MaterialwarehousingEntity materialwarehousingEntity = materialwarehousingService.getById(materialwarehousingMaterial.getMaterialwarehousingId());
                    if (warehousingMaterials.size() == mm) {
                        materialwarehousingEntity.setIsCan("可以");
                        materialwarehousingService.lambdaUpdate()
                                .set(MaterialwarehousingEntity::getIsCan, materialwarehousingEntity.getIsCan())
                                .eq(MaterialwarehousingEntity::getId, materialwarehousingEntity.getId())
                                .update();
                    }
                }

                // 2.更新库存表信息 出库数量，平均价格，库存，总金额
                MaterialQuantityEntity materialQuantityEntity = materialQuantityService.getByMaterialIdAndStorehouseId(deliveryMaterial.getMaterialId(), deliveryMaterial.getStorehouseId());
                BigDecimal deliveryquantity = materialQuantityEntity.getDeliveryquantity() == null ? BigDecimal.ZERO : materialQuantityEntity.getDeliveryquantity();
                BigDecimal quantity = materialQuantityEntity.getQuantity() == null ? BigDecimal.ZERO : materialQuantityEntity.getQuantity();
                BigDecimal total = materialQuantityEntity.getTotal() == null ? BigDecimal.ZERO : materialQuantityEntity.getTotal();
                materialQuantityEntity.setDeliveryquantity(deliveryquantity.subtract(deliveryMaterial.getDeliveryquantity()));
                materialQuantityEntity.setQuantity(quantity.add(deliveryMaterial.getDeliveryquantity()));
                materialQuantityEntity.setTotal(total.add(deliveryMaterial.getTotal()));
                // 平均价格
                if (materialQuantityEntity.getTotal().compareTo(BigDecimal.ZERO) == 0 || materialQuantityEntity.getQuantity().compareTo(BigDecimal.ZERO) == 0) {
                    materialQuantityEntity.setUnitprice(BigDecimal.ZERO);
                } else {
                    materialQuantityEntity.setUnitprice(materialQuantityEntity.getTotal().divide(materialQuantityEntity.getQuantity(), 2));
                }
                materialQuantityService.lambdaUpdate()
                        .set(MaterialQuantityEntity::getDeliveryquantity, materialQuantityEntity.getDeliveryquantity())
                        .set(MaterialQuantityEntity::getQuantity, materialQuantityEntity.getQuantity())
                        .set(MaterialQuantityEntity::getTotal, materialQuantityEntity.getTotal())
                        .set(MaterialQuantityEntity::getUnitprice, materialQuantityEntity.getUnitprice())
                        .eq(MaterialQuantityEntity::getId, materialQuantityEntity.getId())
                        .update();

            }

            // 更新领用单
            MaterialreceiptEntity materialreceiptEntity = materialreceiptService.getById(entity.getMaterialreceiptId());
            materialreceiptEntity.setDeliveryStatus("未出库");
            materialreceiptService.lambdaUpdate()
                    .set(MaterialreceiptEntity::getDeliveryStatus, materialreceiptEntity.getDeliveryStatus())
                    .eq(MaterialreceiptEntity::getId, materialreceiptEntity.getId())
                    .update();

            materialdeliveryRepository.checkCancellation(id, entity);
        }
    }
}